home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / maximus / aselect.zip / ASELECT.MEX < prev    next >
Text File  |  1996-05-27  |  13KB  |  491 lines

  1. // ----------------------------------------------------------------------
  2. //
  3. //  Area Selector v0.2 beta
  4. //
  5. //  Copyright 1996 by Brian C. Lane
  6. //
  7. //  All Rights Reserver
  8. //  This code may not be modified and used in any other piece of code
  9. //  without acknowledging the source (me!)
  10. //
  11. //-----------------------------------------------------------------------
  12. //
  13. //  This code is a work in progress. It currently only allows the user
  14. //  to select the area (file or message, see below). Eventually the user
  15. //  will be able to tag a list of areas to view(subscribe) that can also
  16. //  be packaged for the offline .QWK reader.
  17. //
  18. //  Probably the only thing you will want to change are the colors,
  19. //  defined directly below as GC_*, see MAX.DOC for info on how to set
  20. //  the AVATAR colors.
  21. //
  22. //  ---------------------------------------------------------------------
  23. //
  24. //  This allows a user to walk up and down the areas available on the
  25. //  system and to select one to use by hitting enter. It checks the
  26. //  user's video type and uses the default(ugly) selection method if
  27. //  ANSI isn't supported.
  28. //
  29. // ----------------------------------------------------------------------
  30.  
  31. #include <max.mh>
  32. #include <prm.mh>
  33. #include <xgetch.mh>                    // Use xgetch routine
  34.  
  35.  
  36. //
  37. // Select the version to compile. FSELECT selects files, and MSELECT
  38. // selects message areas.
  39. //
  40. #define FSELECT
  41. //#define MSELECT
  42.  
  43.  
  44. // ----------------------------------------------------------------------
  45. // Color definitions
  46. // ----------------------------------------------------------------------
  47. #define GC_TITLE_BBS    "\x16\x01\x79"
  48. #define GC_TITLE_USER   "\x16\x01\x7e"
  49. #define GC_HELP         COL_GRAY
  50. #define GC_NUM          COL_WHITE
  51. #define GC_UNREAD       COL_LGREEN
  52. #define GC_NAME         COL_WHITE
  53. #define GC_DESC         COL_LBLUE
  54. #define GC_NUM_HI       "\x16\x01\x78"
  55. #define GC_UNREAD_HI    "\x16\x01\x7A"
  56. #define GC_NAME_HI      "\x16\x01\x78"
  57. #define GC_DESC_HI      "\x16\x01\x79"
  58.  
  59.  
  60. #ifdef MSELECT
  61. #define ATYPE msg
  62. #define AREAT _marea
  63. #define ARVAR marea
  64. #define AreaFindFirst msgareafindfirst
  65. #define AreaFindNext  msgareafindnext
  66. #define AreaFindPrev  msgareafindprev
  67. #define AreaFindClose msgareafindclose
  68. #define AreaSelect    msgareaselect
  69. #else
  70. #define ATYPE file
  71. #define AREAT _farea
  72. #define ARVAR farea
  73. #define AreaFindFirst fileareafindfirst
  74. #define AreaFindNext  fileareafindnext
  75. #define AreaFindPrev  fileareafindprev
  76. #define AreaFindClose fileareafindclose
  77. #define AreaSelect    fileareaselect
  78. #endif
  79.  
  80. //========================= Page structure =================================
  81. // Lastfile: This integer defines the last file on this page, in most cases
  82. //           this should equal to 16, except for the last page
  83. // Filename: Contains the filename, BUT!  if filename="", <desc> contains
  84. //           a description that is continued from the last file.
  85. //           And, if filename="z", <desc> is a comment.
  86. // Size: Size of the file
  87. // Date: Date of file as a string
  88. // Desc: Description or comment
  89. // Tagged: TRUE if file is tagged and FALSE if not
  90. struct _page
  91. {
  92.   string: name;
  93.   long: num;
  94.   long: current;
  95.   long: high;
  96.   string: desc;
  97.   int: tagged;
  98. } ;
  99. array [1..20] of struct _page: page;
  100. int:    lastgroup;                      // Lastgroup on the page
  101. int:    pos;                            // Position 1..18
  102. int:    errwin;                         // Indicates if line 25 needs clearing
  103. string: last;                           // Last area selected by the user
  104.  
  105.  
  106. // --------------------------------------------------------------------
  107. // Fill in the page structure with the next 18 groups, starting with
  108. // The next group after the one in page[18].name, unless it is null,
  109. // then start with the top
  110. // --------------------------------------------------------------------
  111. int next_group_page()
  112. {
  113.   int:                  i, x;
  114.   struct AREAT:         a;
  115.  
  116.  
  117.   if ( lastgroup = 0 )
  118.   {
  119.     i:=AreaFindFirst(a, "", AFFO_NODIV);
  120.     if( i = 0 )
  121.     {
  122.       return -1;
  123.     }
  124.   } else {
  125.     i:=AreaFindFirst(a, page[lastgroup].name, AFFO_NODIV);
  126.     if( i = 0 )
  127.     {
  128.       return -2;
  129.     }
  130.  
  131.     i:=AreaFindNext(a);
  132.     if( i = 0 )
  133.     {
  134.       return -3;
  135.     }
  136.   }
  137.  
  138.   print( AVATAR_GOTO, (char)25, (char)1);
  139.   print( COL_WHITE, "Scanning group ");
  140.  
  141.   x := 1;
  142.   while( ( x < 19 ) and i )
  143.   {
  144.     print( AVATAR_GOTO, (char)25, (char)16 );
  145.     print( x );
  146.  
  147. #ifdef MSELECT
  148.     i := AreaSelect( a.name );
  149. #endif
  150.  
  151.     page[x].name := a.name;
  152.     page[x].desc := substr( a.descript, 1, 40);
  153.  
  154. #ifdef MSELECT
  155.     page[x].num := ATYPE.num;
  156.     page[x].current := ATYPE.current;
  157.     page[x].high := ATYPE.high;
  158.  
  159.     i:=AreaFindFirst(a, a.name, AFFO_NODIV);
  160. #endif
  161.  
  162.     i:=AreaFindNext(a);
  163.  
  164.     if( i )
  165.       x := x + 1;
  166.   }
  167.   AreaFindClose();
  168.  
  169.   if ( i )
  170.     lastgroup := x-1;
  171.   else
  172.     lastgroup := x;
  173.  
  174.   return 0;
  175. }
  176.  
  177.  
  178. // ----------------------------------------------------------------------
  179. // Fill in the page structure with the previous 18 groups, starting with
  180. // The previous group before the one in page[1].name, unless it is null,
  181. // then don't do anything.
  182. // ----------------------------------------------------------------------
  183. int prev_group_page()
  184. {
  185.   int:          i, x;
  186.   struct AREAT: a;
  187.  
  188.  
  189.   i:=AreaFindFirst(a, page[1].name, AFFO_NODIV);
  190.   if( i = 0 )
  191.   {
  192.     return -1;
  193.   }
  194.  
  195.   i:=AreaFindPrev(a);
  196.   if( i = 0 )
  197.   {
  198.     return -2;
  199.   }
  200.  
  201.  
  202.   print( AVATAR_GOTO, (char)25, (char)1);
  203.   print( COL_WHITE, "Scanning group ");
  204.  
  205.   x := 18;
  206.   while( ( x > 0 ) and i )
  207.   {
  208.     print( AVATAR_GOTO, (char)25, (char)16 );
  209.     print( strpadleft( itostr( x ), 2, ' ') );
  210.  
  211. #ifdef MSELECT
  212.     i := AreaSelect( a.name );
  213. #endif
  214.  
  215.     page[x].name := a.name;
  216.     page[x].desc := substr( a.descript, 1, 40);
  217.  
  218. #ifdef MSELECT
  219.     page[x].num := ATYPE.num;
  220.     page[x].current := ATYPE.current;
  221.     page[x].high := ATYPE.high;
  222.  
  223.     i:=AreaFindFirst(a, a.name, AFFO_NODIV);
  224. #endif
  225.  
  226.     i:=AreaFindPrev(a);
  227.  
  228.     if( i )
  229.       x := x - 1;
  230.   }
  231.   AreaFindClose();
  232.  
  233.   lastgroup := 18;
  234.  
  235.   return 0;
  236. }
  237.  
  238.  
  239.  
  240.  
  241. // ----------------------------------------------------------------------
  242. // Update the display with the current page information
  243. //
  244. // Shows the title bar with the BBS name and ??
  245. // Shows the help bar at the bottom of the screen
  246. //
  247. // Shows 18 groups in format:
  248. //   #   [unread msgs]   name     description
  249. //
  250. // ----------------------------------------------------------------------
  251. int show_group_page()
  252. {
  253.   int:  x;
  254.   int:  unread;
  255.  
  256.   print( AVATAR_CLS );
  257.  
  258.   print( GC_TITLE_BBS, "  ", strpad( prm_string(PRM_SYSNAME), 38, ' ' ), GC_TITLE_USER, strpadleft( usr.name, 38, ' ' ), "  " );
  259.  
  260.   for( x := 1; x <= lastgroup; x := x + 1 )
  261.   {
  262.     print( AVATAR_GOTO, (char)(x+2), (char)2 );
  263. #ifdef MSELECT
  264.     unread := page[x].high - page[x].current;
  265.     print( GC_NUM, strpadleft( itostr(x), 3, ' '), GC_UNREAD, strpadleft( itostr(unread), 3, ' '), "  ", GC_NAME, strpad( page[x].name, 30, ' '), GC_DESC, page[x].desc);
  266. #else
  267.     print( GC_NUM, strpadleft( itostr(x), 3, ' '), "  ", GC_NAME, strpad( page[x].name, 30, ' '), GC_DESC, page[x].desc);
  268. #endif
  269.   }
  270.  
  271.   print( AVATAR_GOTO, (char)22, (char)12 );
  272.  
  273. #ifdef MSELECT
  274.   print( GC_HELP, "[arrows] = select       [enter] = read       [Q] = Quit" );
  275. #else
  276.   print( GC_HELP, "[arrows] = select       [enter] = goto       [Q] = Quit" );
  277. #endif
  278.  
  279.   // Return cursor to an out of the way place
  280.   print( AVATAR_GOTO, (char)1, (char)1 );
  281.  
  282.   return 0;
  283. }
  284.  
  285.  
  286.  
  287. // --------------------------------------------------------------------
  288. // Hilight one line in the list of groups
  289. // --------------------------------------------------------------------
  290. int hilight_group( int: x )
  291. {
  292.   int:  unread;
  293.  
  294.   print( AVATAR_GOTO, (char)(x+2), (char)1 );
  295.  
  296. #ifdef MSELECT
  297.   unread := page[x].high - page[x].current;
  298.   print( GC_NUM_HI, " ", strpadleft( itostr(x), 3, ' '), GC_UNREAD_HI, strpadleft( itostr(unread), 3, ' '), "  ", GC_NAME_HI, strpad( page[x].name, 30, ' '), GC_DESC_HI, strpad( page[x].desc, 41, ' ') );
  299. #else
  300.   print( GC_NUM_HI, " ", strpadleft( itostr(x), 3, ' '), "  ", GC_NAME_HI, strpad( page[x].name, 30, ' '), GC_DESC_HI, strpad( page[x].desc, 44, ' ') );
  301. #endif
  302.  
  303.   print( AVATAR_GOTO, (char)(x+2), (char)1 );
  304. }
  305.  
  306.  
  307. // --------------------------------------------------------------------
  308. // Un-Hilight one line in the list of groups
  309. // --------------------------------------------------------------------
  310. int unhilight_group( int: x )
  311. {
  312.   int:  unread;
  313.  
  314.   print( AVATAR_GOTO, (char)(x+2), (char)1 );
  315.  
  316. #ifdef MSELECT
  317.   unread := page[x].high - page[x].current;
  318.   print( GC_NUM, " ", strpadleft( itostr(x), 3, ' '), GC_UNREAD, strpadleft( itostr(unread), 3, ' '), "  ", GC_NAME, strpad( page[x].name, 30, ' '), GC_DESC, strpad( page[x].desc, 41, ' ') );
  319. #else
  320.   print( GC_NUM, " ", strpadleft( itostr(x), 3, ' '), "  ", GC_NAME, strpad( page[x].name, 30, ' '), GC_DESC, strpad( page[x].desc, 44, ' ') );
  321. #endif
  322.  
  323.   print( AVATAR_GOTO, (char)(x+2), (char)1 );
  324. }
  325.  
  326.  
  327. // --------------------------------------------------------------------
  328. // Handle keypresses in the group window
  329. // --------------------------------------------------------------------
  330. int group_key( int: k )
  331. {
  332.   // Clear the error window
  333.   if( errwin = 1 )
  334.   {
  335.     print( AVATAR_GOTO, (char)25, (char)1 );
  336.     print( strpad( " ", 20, ' ' ) );
  337.     errwin := 0;
  338.   }
  339.  
  340.   if( k = X_UP )
  341.   {
  342.     // If not at top of page, move up 1
  343.     if( pos > 1 )
  344.     {
  345.       unhilight_group( pos );
  346.       pos := pos - 1;
  347.       hilight_group( pos );
  348.     } else {
  349.       // Move up a page
  350.       if ( prev_group_page() = 0 )
  351.       {
  352.         pos := 18;
  353.         show_group_page();
  354.         hilight_group( pos );
  355.       }
  356.     }
  357.   }
  358.  
  359.   if( k = X_PAGEUP )
  360.   {
  361.     // Move up a page
  362.     if( prev_group_page() = 0 )
  363.     {
  364.       pos := 18;
  365.       show_group_page();
  366.       hilight_group( pos );
  367.     }
  368.   }
  369.  
  370.   if( k = X_DOWN )
  371.   {
  372.     // If not at end of page move down 1
  373.     if( pos < lastgroup )
  374.     {
  375.       unhilight_group( pos );
  376.       pos := pos + 1;
  377.       hilight_group( pos );
  378.     } else if( lastgroup = 18 ) {
  379.       // Move down a page
  380.       if( next_group_page() = 0 )
  381.       {
  382.         pos := 1;
  383.         show_group_page();
  384.         hilight_group( pos );
  385.       }
  386.     }
  387.   }   
  388.  
  389.   if( k = X_PAGEDOWN )
  390.   {
  391.     // Move up a page
  392.     if( next_group_page() = 0 )
  393.     {
  394.       pos := 1;
  395.       show_group_page();
  396.       hilight_group( pos );
  397.     }
  398.   }
  399.  
  400.   return 0;
  401. }
  402.  
  403.  
  404.  
  405. // --------------------------------------------------------------------
  406. // Show a display of 1-16 groups. Keep a list of their names and
  407. // info in a 16 entry array (read/unread, name, description)
  408. // --------------------------------------------------------------------
  409.  
  410. int main()
  411. {
  412.   int:  stat, key, state;
  413.   char: nonstop;
  414.  
  415.   lastgroup := 0;                       // Start at top
  416.  
  417.  
  418.   // Check user's video state and call normal routine if ANSI not supported
  419.   if( usr.video < VIDEO_ANSI )
  420.   {
  421.  
  422. #ifdef MSELECT
  423.     msg_area();
  424. #else
  425.     file_area();
  426. #endif
  427.  
  428.     return 0;
  429.   }
  430.  
  431.   print(AVATAR_CLS);
  432.  
  433.   last := ARVAR.name;                           // Remember the last area
  434.  
  435.   if( ( stat := next_group_page() ) < 0 )
  436.   {
  437.     print("Error:" + itostr(stat) + " Getting first page\n");
  438.     return -1;
  439.   }
  440.  
  441.   // Show the first page of groups
  442.   stat := show_group_page();
  443.  
  444.   pos := 1;
  445.   hilight_group( pos );
  446.  
  447.   state := 0;
  448.   while( stat = 0 )
  449.   {
  450.     key := xgetch();
  451.  
  452.     if( key = 'Q' or key = 'q' )
  453.     {
  454.       stat := AreaSelect( last );
  455.       stat := 1;
  456.     } else {
  457.       if( state = 0 )
  458.       {
  459.         if( key = 0 )
  460.           key := xgetch();
  461.  
  462.         // ENTER was hit, select the area
  463.         if( key = 0x0D )
  464.         {
  465.           stat := AreaSelect( page[pos].name );
  466.  
  467.           // check for an error
  468.           if( stat = 0 )
  469.           {
  470.             print( AVATAR_GOTO, (char)25, (char)1 );
  471.             print( COL_LRED, "Error opening area ", page[pos].name );
  472.             errwin := 1;
  473.           } else {
  474.             stat := 1;
  475.           }
  476.         } else {
  477.           stat := group_key( key );
  478.         }
  479.       } else if( state = 1 ) {
  480. //        stat := thread_key( key );
  481.       }
  482.     }
  483.   }
  484.  
  485.   print( AVATAR_CLS );
  486.  
  487.   return 0;
  488. }
  489.  
  490.  
  491.